package dantzig_wolfe_decomposition;

import gurobi.GRB;
import gurobi.GRBEnv;
import gurobi.GRBException;
import gurobi.GRBLinExpr;
import gurobi.GRBModel;
import gurobi.GRBVar;

import Jama.Matrix;

public class SubProblem {

    private GRBEnv env;
    private GRBModel model;
    private int xNum;

    public Matrix solutions; // 决策变量的值，列向量
    public double objVal;

    SubProblem(int index, Matrix shadowPrice) {
        xNum = Dataset.benefit[index].length;
        try {
            env = new GRBEnv(true);
            env.start();
            model = new GRBModel(env);
            model.set("OutputFlag", "0");

            // 创建决策变量
            GRBVar[] x = model.addVars(xNum, GRB.CONTINUOUS);

            // 设置目标函数
            GRBLinExpr expr = new GRBLinExpr();
            Matrix temp = new Matrix(1, xNum, 0);
            for (int i = 0; i < xNum; i++) {
                temp.set(0, i, shadowPrice.get(0, 0) * Dataset.iron[index][i] - Dataset.benefit[index][i]);
            }
            expr.addTerms(temp.getArray()[0], x);
            expr.addConstant(shadowPrice.get(0, index + 1));
            model.setObjective(expr, GRB.MINIMIZE);

            // 添加约束
            expr = new GRBLinExpr();
            expr.addTerms(Dataset.coal[index], x);
            model.addConstr(expr, GRB.LESS_EQUAL, Dataset.constraint[index][0], "c0");
            expr = new GRBLinExpr();
            expr.addTerms(Dataset.furnace[index], x);
            model.addConstr(expr, GRB.LESS_EQUAL, Dataset.constraint[index][1], "c1");

        } catch (GRBException e) {
            System.out.println("Error code: " + e.getErrorCode() + ". " + e.getMessage());
        }
    }

    public void solve() {

        try {

            // 求解模型
            model.optimize();

            // 读取决策变量的值
            solutions = new Matrix(xNum, 1, 0);
            for (int i = 0; i < xNum; i++) {
                solutions.set(i, 0, model.getVars()[i].get(GRB.DoubleAttr.X));
            }

            objVal = model.get(GRB.DoubleAttr.ObjVal);

            model.dispose();
            env.dispose();

        } catch (GRBException e) {
            System.out.println("Error code: " + e.getErrorCode() + ". " + e.getMessage());
        }

    }

}
